Experiments and questions / OpenGL backend

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_pyglet.py)

Second, I’ve been experimenting with proper anti-alias technics (using shaders) and the results are not so bad so far (IMHO) :

Antialiased line with thickness varying by 0.1 pixels:

http://www.loria.fr/~rougier/tmp/aa-line.png

(don’t paid attention to the cap, it’s not done yet)

Antialiased circles (small circles position is increased by 0.1 pixels)

http://www.loria.fr/~rougier/tmp/aa-circle.png

(I can post source code if anyone is interested)

I don’t know yet if all matplotlib artists can be drawing using these technics.

My question relates to the cairo backend that now seems to support gl and shaders. Does anyone know the status of the gl-backend and how it would improve performances of matplotlib ? (I had a hard time finding any information).

Nicolas

Nicolas,

I want to immediately encourage you to continue on your efforts. PLEASE make a fork on github so that we may be able to experiment better.

Cheers!
Ben Root

···

On Wednesday, July 27, 2011, Nicolas Rougier <Nicolas.Rougier@…922…> 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 <http://www.loria.fr/~rougier/tmp/backend_pyglet.py> and the test file is at test_backend_pyglet.py <http://www.loria.fr/~rougier/tmp/test_backend_pyglet.py>)

Second, I’ve been experimenting with proper anti-alias technics (using shaders) and the results are not so bad so far (IMHO) :
Antialiased line with thickness varying by 0.1 pixels:
http://www.loria.fr/~rougier/tmp/aa-line.png

(don’t paid attention to the cap, it’s not done yet)

Antialiased circles (small circles position is increased by 0.1 pixels)
http://www.loria.fr/~rougier/tmp/aa-circle.png

(I can post source code if anyone is interested)
I don’t know yet if all matplotlib artists can be drawing using these technics.

My question relates to the cairo backend that now seems to support gl and shaders. Does anyone know the status of the gl-backend and how it would improve performances of matplotlib ? (I had a hard time finding any information).

Nicolas

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 <Nicolas.Rougier@…922…> 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 <http://www.loria.fr/~rougier/tmp/backend_pyglet.py> and the test file is at test_backend_pyglet.py <http://www.loria.fr/~rougier/tmp/test_backend_pyglet.py>)

Second, I’ve been experimenting with proper anti-alias technics (using shaders) and the results are not so bad so far (IMHO) :
Antialiased line with thickness varying by 0.1 pixels:
http://www.loria.fr/~rougier/tmp/aa-line.png

(don’t paid attention to the cap, it’s not done yet)

Antialiased circles (small circles position is increased by 0.1 pixels)
http://www.loria.fr/~rougier/tmp/aa-circle.png

(I can post source code if anyone is interested)
I don’t know yet if all matplotlib artists can be drawing using these technics.

My question relates to the cairo backend that now seems to support gl and shaders. Does anyone know the status of the gl-backend and how it would improve performances of matplotlib ? (I had a hard time finding any information).

Nicolas

Nicolas,

I want to immediately encourage you to continue on your efforts. PLEASE make a fork on github so that we may be able to experiment better.

Cheers!
Ben Root

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] Mike
···

http://codespeak.net/pypy/dist/pypy/tool/lsprofcalltree.py

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 <Nicolas.Rougier@...922...          >

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 <http://www.loria.fr/~rougier/tmp/backend_pyglet.py > and
the test file is at test_backend_pyglet.py <http://www.loria.fr/~rougier/tmp/test_backend_pyglet.py>)

      >

      > Second, I've been experimenting with proper anti-alias

technics (using shaders) and the results are not so bad so far
(IMHO) :

      > Antialiased line with thickness varying by 0.1 pixels:

      > [http://www.loria.fr/~rougier/tmp/aa-line.png](http://www.loria.fr/%7Erougier/tmp/aa-line.png)

      > (don't paid attention to the cap, it's not done yet)

      >

      > Antialiased circles (small circles position is increased

by 0.1 pixels)

      > [http://www.loria.fr/~rougier/tmp/aa-circle.png](http://www.loria.fr/%7Erougier/tmp/aa-circle.png)

      > (I can post source code if anyone is interested)

      > I don't know yet if all matplotlib artists can be drawing

using these technics.

      >

      > My question relates to the cairo backend that now seems

to support gl and shaders. Does anyone know the status of the
gl-backend and how it would improve performances of matplotlib
? (I had a hard time finding any information).

      >

      > Nicolas



      Nicolas,



      I want to immediately encourage you to continue on your

efforts. PLEASE make a fork on github so that we may be able
to experiment better.

      Cheers!

      Ben Root


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.


Matplotlib-devel mailing list

-- Michael Droettboom
Science Software Branch
Space Telescope Science Institute
Baltimore, Maryland, USA

http://p.sf.net/sfu/slashdot-survey


Matplotlib-devel@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-devel

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)

1 0.004 0.004 16.587 16.587 test_backend_pyglet.py:1()

1 0.000 0.000 14.000 14.000 pyplot.py:123(show)

1 0.000 0.000 14.000 14.000 backend_pyglet.py:214(show)

1 0.000 0.000 13.951 13.951 init.py:115(run)

1 0.000 0.000 13.951 13.951 base.py:117(run)

1 0.009 0.009 13.949 13.949 base.py:149(_run_estimated)

1000 0.018 0.000 13.639 0.014 base.py:244(idle)

1119/1116 0.009 0.000 13.378 0.012 event.py:318(dispatch_event)

1004 0.006 0.000 13.340 0.013 init.py:1148(dispatch_event)

1000 0.002 0.000 13.326 0.013 backend_pyglet.py:319(on_draw)

1000 0.013 0.000 13.324 0.013 backend_pyglet.py:324(draw)

1000 0.004 0.000 13.001 0.013 backend_pyglet.py:342(_render_figure)

60000/1000 0.204 0.000 12.977 0.013 artist.py:53(draw_wrapper)

1000 0.023 0.000 12.970 0.013 figure.py:805(draw)

1000 0.046 0.000 12.775 0.013 axes.py:1866(draw)

2000 0.046 0.000 11.791 0.006 axis.py:1029(draw)

10000 0.098 0.000 8.521 0.001 axis.py:219(draw)

21000 0.710 0.000 6.467 0.000 lines.py:463(draw)

20000 0.030 0.000 2.301 0.000 transforms.py:2234(get_transformed_points_and_affine)

21000 0.093 0.000 2.245 0.000 transforms.py:2224(_revalidate)

1 0.001 0.001 2.081 2.081 pylab.py:1()

1 0.001 0.001 2.080 2.080 pylab.py:215()

12/6 0.007 0.001 2.036 0.339 {import}

1 0.001 0.001 1.937 1.937 pyplot.py:15()

1 0.000 0.000 1.935 1.935 init.py:14(pylab_setup)

1 0.001 0.001 1.931 1.931 backend_pyglet.py:55()

1 0.011 0.011 1.929 1.929 init.py:94()

68000/64000 0.450 0.000 1.824 0.000 transforms.py:1732(transform)

15000 0.381 0.000 1.726 0.000 text.py:514(draw)

2000 0.035 0.000 1.711 0.001 axis.py:977(_get_tick_bboxes)

10000 0.091 0.000 1.668 0.000 text.py:713(get_window_extent)

64605 0.694 0.000 1.520 0.000 path.py:83(init)

24000 0.067 0.000 1.491 0.000 transforms.py:1155(transform_path_non_affine)

20041 0.435 0.000 1.430 0.000 lines.py:386(recache)

44000 0.118 0.000 1.385 0.000 transforms.py:1761(transform_non_affine)

164452 1.340 0.000 1.340 0.000 {numpy.core.multiarray.array}

20000 0.076 0.000 1.137 0.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

···

http://codespeak.net/pypy/dist/pypy/tool/lsprofcalltree.py

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 <Nicolas.Rougier@...983...2...          >

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 <http://www.loria.fr/~rougier/tmp/backend_pyglet.py > and
the test file is at test_backend_pyglet.py <http://www.loria.fr/~rougier/tmp/test_backend_pyglet.py>)

      >

      > Second, I've been experimenting with proper anti-alias

technics (using shaders) and the results are not so bad so far
(IMHO) :

      > Antialiased line with thickness varying by 0.1 pixels:

      > [http://www.loria.fr/~rougier/tmp/aa-line.png](http://www.loria.fr/%7Erougier/tmp/aa-line.png)

      > (don't paid attention to the cap, it's not done yet)

      >

      > Antialiased circles (small circles position is increased

by 0.1 pixels)

      > [http://www.loria.fr/~rougier/tmp/aa-circle.png](http://www.loria.fr/%7Erougier/tmp/aa-circle.png)

      > (I can post source code if anyone is interested)

      > I don't know yet if all matplotlib artists can be drawing

using these technics.

      >

      > My question relates to the cairo backend that now seems

to support gl and shaders. Does anyone know the status of the
gl-backend and how it would improve performances of matplotlib
? (I had a hard time finding any information).

      >

      > Nicolas



      Nicolas,



      I want to immediately encourage you to continue on your

efforts. PLEASE make a fork on github so that we may be able
to experiment better.

      Cheers!

      Ben Root


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.


Matplotlib-devel mailing list
http://p.sf.net/sfu/slashdot-survey


Matplotlib-devel@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-devel

-- Michael Droettboom
Science Software Branch
Space Telescope Science Institute
Baltimore, Maryland, USA

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. :wink: 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

real    0m15.211s
user    0m15.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

real    0m14.038s
user    0m13.713s
sys     0m0.256s

> time python test_backend_speed.py 100 agg

real    0m23.038s
user    0m22.845s
sys     0m0.132s

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

real    0m15.251s
user    0m14.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
···

http://codespeak.net/pypy/dist/pypy/tool/lsprofcalltree.py

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 <Nicolas.Rougier@...922...
              >

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 <http://www.loria.fr/~rougier/tmp/backend_pyglet.py
> and
the test file is at test_backend_pyglet.py <http://www.loria.fr/~rougier/tmp/test_backend_pyglet.py>)

              >

              > Second, I've been experimenting with proper

anti-alias technics (using shaders) and the results
are not so bad so far (IMHO) :

              > Antialiased line with thickness varying by 0.1

pixels:

              > [http://www.loria.fr/~rougier/tmp/aa-line.png](http://www.loria.fr/%7Erougier/tmp/aa-line.png)

              > (don't paid attention to the cap, it's not done

yet)

              >

              > Antialiased circles (small circles position is

increased by 0.1 pixels)

              > [http://www.loria.fr/~rougier/tmp/aa-circle.png](http://www.loria.fr/%7Erougier/tmp/aa-circle.png)

              > (I can post source code if anyone is interested)

              > I don't know yet if all matplotlib artists can be

drawing using these technics.

              >

              > My question relates to the cairo backend that now

seems to support gl and shaders. Does anyone know the
status of the gl-backend and how it would improve
performances of matplotlib ? (I had a hard time
finding any information).

              >

              > Nicolas



              Nicolas,



              I want to immediately encourage you to continue on

your efforts. PLEASE make a fork on github so that we
may be able to experiment better.

              Cheers!

              Ben Root


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.


Matplotlib-devel mailing list
http://p.sf.net/sfu/slashdot-survey


Matplotlib-devel@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-devel

-- Michael Droettboom
Science Software Branch
Space Telescope Science Institute
Baltimore, Maryland, USA

Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
http://p.sf.net/sfu/slashdot-survey


Matplotlib-devel@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-devel

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

···

On Fri, Jul 29, 2011 at 11:05 AM, Michael Droettboom <mdroe@…31…> 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. :wink: 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



real    0m15.211s

user    0m15.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



real    0m14.038s

user    0m13.713s

sys     0m0.256s



> time python test_backend_speed.py 100 agg



real    0m23.038s

user    0m22.845s

sys     0m0.132s



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



real    0m15.251s

user    0m14.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

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

···

http://codespeak.net/pypy/dist/pypy/tool/lsprofcalltree.py

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 <Nicolas.Rougier@...922...
              >

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 <http://www.loria.fr/~rougier/tmp/backend_pyglet.py
> and
the test file is at test_backend_pyglet.py <http://www.loria.fr/~rougier/tmp/test_backend_pyglet.py>)

              >

              > Second, I've been experimenting with proper

anti-alias technics (using shaders) and the results
are not so bad so far (IMHO) :

              > Antialiased line with thickness varying by 0.1

pixels:

              > [http://www.loria.fr/~rougier/tmp/aa-line.png](http://www.loria.fr/%7Erougier/tmp/aa-line.png)

              > (don't paid attention to the cap, it's not done

yet)

              >

              > Antialiased circles (small circles position is

increased by 0.1 pixels)

              > [http://www.loria.fr/~rougier/tmp/aa-circle.png](http://www.loria.fr/%7Erougier/tmp/aa-circle.png)

              > (I can post source code if anyone is interested)

              > I don't know yet if all matplotlib artists can be

drawing using these technics.

              >

              > My question relates to the cairo backend that now

seems to support gl and shaders. Does anyone know the
status of the gl-backend and how it would improve
performances of matplotlib ? (I had a hard time
finding any information).

              >

              > Nicolas



              Nicolas,



              I want to immediately encourage you to continue on

your efforts. PLEASE make a fork on github so that we
may be able to experiment better.

              Cheers!

              Ben Root


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.


Matplotlib-devel mailing list
http://p.sf.net/sfu/slashdot-survey


Matplotlib-devel@…953…ge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-devel

-- Michael Droettboom
Science Software Branch
Space Telescope Science Institute
Baltimore, Maryland, USA

Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
http://p.sf.net/sfu/slashdot-survey


Matplotlib-devel@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-devel

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