| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
| cur = ctx.get_current_point() | ||
| ctx.curve_to( | ||
| *np.concatenate([cur / 3 + points[:2] * 2 / 3, | ||
| points[:2] * 2 / 3 + points[-2:] / 3])) |
There was a problem hiding this comment.
Not sure why this is different than before?
Sorry, something went wrong.
There was a problem hiding this comment.
previous version was actually incorrect (see basically https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Degree_elevation)..
Sorry, something went wrong.
|
|
||
|
|
||
| def _convert_paths(ctx, paths, transforms, clip=None): | ||
| return (_convert_paths_fast if HAS_CAIRO_CFFI else _convert_paths_slow)( |
There was a problem hiding this comment.
Maybe if at top-level would be quicker/simpler?
Sorry, something went wrong.
There was a problem hiding this comment.
By top-level, I meant if HAS_CAIRO_CFFI: _convert_paths = _convert_paths_fast ...
Sorry, something went wrong.
|
|
||
| def _convert_paths_fast(ctx, paths, transforms, clip=None): | ||
| # We directly convert to the internal representation used by cairo, for | ||
| # which ABI compatibility is guaranteed. The layout is for each item is |
There was a problem hiding this comment.
s/is for/for/
Sorry, something went wrong.
| transform = (transform | ||
| + Affine2D().scale(1.0, -1.0).translate(0, self.height)) | ||
|
|
||
| + Affine2D().scale(1, -1).translate(0, self.height)) |
There was a problem hiding this comment.
Could be += to make one line?
Sorry, something went wrong.
There was a problem hiding this comment.
transforms are mutable but don't implement iadd (so += actually doesn't modify the transform in place), but I was too lazy to check and want to make clear that we're indeed not mutating the transform.
Sorry, something went wrong.
|
|
||
| transform = (transform | ||
| + Affine2D().scale(1.0, -1.0).translate(0, self.height)) | ||
| + Affine2D().scale(1, -1).translate(0, self.height)) |
There was a problem hiding this comment.
Also +=?
Sorry, something went wrong.
There was a problem hiding this comment.
as above
Sorry, something went wrong.
| self.convert_path( | ||
| ctx, marker_path, marker_trans + Affine2D().scale(1.0, -1.0)) | ||
| _convert_path( | ||
| ctx, marker_path, marker_trans + Affine2D().scale(1, -1)) |
There was a problem hiding this comment.
This fits on one line, no?
Sorry, something went wrong.
| vars(gc).update(gc_vars) | ||
| for k, v in gc_vars.items(): | ||
| try: | ||
| getattr(gc, "set" + k)(v) |
There was a problem hiding this comment.
No underscore is needed?
Sorry, something went wrong.
There was a problem hiding this comment.
Actually no, I'm just copying the __dict__ of the original gc, and (kind of an implementation detail...) GraphicsContextBase stores "property" foo (accessed by get/set_foo) in ._foo). Not very elegant I admit.
Sorry, something went wrong.
| antialiaseds, urls, offset_position): | ||
| path, transform = path_id | ||
| transform = (Affine2D(transform.get_matrix()).translate(xo, yo) | ||
| + Affine2D().scale(1, -1).translate(0, self.height)) |
There was a problem hiding this comment.
Why do you need the second Affine2D?
Sorry, something went wrong.
There was a problem hiding this comment.
I don't.
Sorry, something went wrong.
| if new_key == reuse_key: | ||
| grouped_draw.append((path, transform)) | ||
| else: | ||
| _draw_paths() |
There was a problem hiding this comment.
Do we need to worry about draw order and such here?
Sorry, something went wrong.
There was a problem hiding this comment.
The draw order is maintained, it's just that I batch the draws that use the same gc together.
Sorry, something went wrong.
| as_int[::4][cairo_type_positions] = codes | ||
| as_int[1::4][cairo_type_positions] = cairo_type_sizes | ||
| mask[::2][cairo_type_positions] = mask[1::2][cairo_type_positions] = False | ||
| as_float[mask] = vertices.ravel() |
There was a problem hiding this comment.
Could be re-arranged slightly to keep the int and float bits together.
Sorry, something went wrong.
There was a problem hiding this comment.
Not sure what you meant?
Sorry, something went wrong.
There was a problem hiding this comment.
Well, you start with a buffer, make an int version, then a float version, then a mask (which is for float). But then go back to filling the int version, modifying the mask (which is float stuff again), then fill the float version. So I mean more like:
buf = np.empty(cairo_num_data * 16, np.uint8)
as_int = np.frombuffer(buf.data, np.int32)
as_int[::4][cairo_type_positions] = codes
as_int[1::4][cairo_type_positions] = cairo_type_sizes
as_float = np.frombuffer(buf.data, np.float64)
mask = np.ones_like(as_float, bool)
mask[::2][cairo_type_positions] = mask[1::2][cairo_type_positions] = False
as_float[mask] = vertices.ravel()
Sorry, something went wrong.
|
Comments addressed. |
Sorry, something went wrong.
|
comments addressed |
Sorry, something went wrong.
|
Generally, I don't see a problem with this change, but using your microbenchmark, I can't seem to reproduce the speedup you see: $ python3 examples/mplot3d/wire3d_animation.py
Matplotlib version: 2.1.1.post1307.dev0+g84008ea05
Backend: TkAgg
Average FPS: 19.965329
$ python3 examples/mplot3d/wire3d_animation.py
/usr/lib/python3.6/site-packages/cairocffi/surfaces.py:651: UserWarning: implicit cast from 'char *' to a different pointer type: will be forbidden in the future (check that the types are as you expect; use an explicit ffi.cast() if they are correct)
ffi.cast('char*', address), format, width, height, stride)
Matplotlib version: 2.1.1.post1307.dev0+g84008ea05
Backend: GTK3Agg
Average FPS: 20.217351
$ python3 examples/mplot3d/wire3d_animation.py
Matplotlib version: 2.1.1.post1307.dev0+g84008ea05
Backend: agg
Average FPS: 22.100502
$ python3 examples/mplot3d/wire3d_animation.py
Matplotlib version: 2.1.1.post1307.dev0+g84008ea05
Backend: GTK3Cairo
Average FPS: 12.131168
$ python3 examples/mplot3d/wire3d_animation.py
Matplotlib version: 2.1.1.post1307.dev0+g84008ea05
Backend: cairo
Average FPS: 70.399400
vs. $ python3 examples/mplot3d/wire3d_animation.py
Matplotlib version: 2.1.1.post18.dev0+gebcfd908c
Backend: TkAgg
Average FPS: 18.767531
$ python3 examples/mplot3d/wire3d_animation.py
/usr/lib/python3.6/site-packages/cairocffi/surfaces.py:651: UserWarning: implicit cast from 'char *' to a different pointer type: will be forbidden in the future (check that the types are as you expect; use an explicit ffi.cast() if they are correct)
ffi.cast('char*', address), format, width, height, stride)
Matplotlib version: 2.1.1.post18.dev0+gebcfd908c
Backend: GTK3Agg
Average FPS: 19.497821
$ python3 examples/mplot3d/wire3d_animation.py
Matplotlib version: 2.1.1.post18.dev0+gebcfd908c
Backend: agg
Average FPS: 21.796568
$ python3 examples/mplot3d/wire3d_animation.py
Matplotlib version: 2.1.1.post18.dev0+gebcfd908c
Backend: GTK3Cairo
Average FPS: 12.018317
$ python3 examples/mplot3d/wire3d_animation.py
Matplotlib version: 2.1.1.post18.dev0+gebcfd908c
Backend: cairo
Average FPS: 68.990914
|
Sorry, something went wrong.
|
Are you certain your gtk3cairo is using cairocffi rather than pycairo (which is not accelerated by this PR)? |
Sorry, something went wrong.
|
OK, I'm not really sure what happened, but I just tried again and I get 12.705427 vs. 17.470702 now. |
Sorry, something went wrong.
There was a problem hiding this comment.
Not a cario expert, but look good to me.
Not really clear with the naming of convert_paths. To me convert feels like it should return the converted object. Maybe apply_paths? If that's not good, please add a short docstring to the convert functions.
Sorry, something went wrong.
flatten() always makes a copy, whereas ravel() does not.
The removed pair of ctx.save and ctx.restore was clearly unnecessary (the outer one is still there, and the font is reset at each loop iteration).
Improves the performance of mplot3d/wire3d_animation on the gtk3cairo backend from ~8.3fps to ~10.5fps (as a comparison, gtk3agg is at ~16.2fps).
Further increase the performance of mplot3d/wire3d_animation on the gtk3cairo backend from ~10.5fps to ~11.6fps (as a comparison, gtk3agg is at ~16.2fps).
For the slow code path, implement the degree elevation formula. For the fast code path, the path cleaner was already handling this for us, converting everything to lines.
|
Renamed to _append_path, which matches the name of the function in the cairo API: https://cairographics.org/manual/cairo-Paths.html#cairo-append-path |
Sorry, something went wrong.
|
Would it help you if pycairo had something like cairo.Path.create_for_data(buffer, num_data) ? |
Sorry, something went wrong.
|
I moved my efforts to just doing everything in C(++) (https://github.com/anntzer/mplcairo) but I guess such a method can't hurt in general... |
Sorry, something went wrong.
ok
yeah, but it's unmaintained atm |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
When using cairocffi only:
Accelerate Path drawing by directly constructing a cairo_path_t using numpy operations rather than repeatedly calling the cairo API to add one point at a time.
Accelerate PathCollection drawing by concatenating Paths that have the same drawing parameters (color, etc., i.e. GraphicsContext attributes).
Minor additional performance improvements (remove an unneeded ndarray copy and an unneeded context save/restore pair).
Overall, this brings the performance of examples/mplot3d/wire3d_animation.py (used as a microbenchmark) from ~8.3fps to ~11.6fps on the same computer (just optimizing Paths instead of PathCollections gives ~10.5fps), using the gtk3cairo backend. As a comparison point, the gtk3agg backend renders ~16.2fps for that example.
From profiling, I believe that further improvements (on that same microbenchmark) could be achieved by improving the text drawing (currently, we use the "toy" API, which is unfortunately the only one exposed by cairocffi so far; additionally, I am not certain whether ft2font exposes pointers to the underlying freetype structures).
Or (for other performance tests) draw_markers could probably also benefit from a similar approach as this PR.