FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

COMPAT: use tkagg backend on PyPy by mattip · Pull Request #9356 · matplotlib/matplotlib · GitHub

Repository navigation

COMPAT: use tkagg backend on PyPy - #9356

Merged
tacaswell merged 12 commits into
matplotlib:masterfrom
mattip:tkagg-cffi
Jan 12, 2018
Merged

tacaswell merged 12 commits into
matplotlib:masterfrom
mattip:tkagg-cffi

Conversation

mattip commented Oct 11, 2017 •
edited
Loading

Copy link
Copy Markdown
Contributor

PR Summary

the tkagg::blitfunction uses the id built-in to obtain memory adresses. This is not compatible with PyPy. I have written a proof-of-concept alternative blit function that uses a pure-python _tkagg backend via CFFI. Since CPython prefers a c-extension (_tkagg.so) over a python file (_tkagg.py) and PyPy reverses this, the two implementations can live side by side.

It is working but not yet complete:

  • on the matplotlib side I should probably only conditionally build the _tkagg c-extension on CPython
  • on the PyPy side the serialization/deserialization of a numpy ndarray should not make a copy of the data
  • updating only a bbox of data not supported yet
  • documentation

but I wanted to see if this approach is acceptable before continuing. Any thoughts?

Edit: now point three (bbox handling) is complete
Edit: (5.Nov.17) now points one and two are done, and documentation does not change

anntzer commented Oct 11, 2017 •
edited
Loading

Copy link
Copy Markdown
Contributor

Looks like the only problematic use of id() is to get the underlying address of the ndarray object (the PyObject, not the memory buffer), right? I would suggest instead just passing a memoryview object, which contains all the relevant information even in Py2 (https://docs.python.org/2/library/stdtypes.html#memoryview), and adapting the extension code to accept such an input (it's all private anyways).

Actually now that I look at it it's not clear whether tk.call can pass memoryviews, but you can also just pass in the address of the underlying buffer and the size and strides of the array (and fix the extension code accordingly). The address of the underlying buffer is accessible at t.__array_interface__["data"] (https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.interface.html#__array_interface__).

If possible, I'd prefer avoid too much pypy specific code, because I fear it's quite likely to bitrot...

tacaswell added this to the 2.2 (next feature release) milestone Oct 11, 2017

mattip commented Oct 16, 2017

Copy link
Copy Markdown
Contributor Author

@anntzer thanks for picking this up.

I tried to modify the id() calls as you said, but have not been able to get load_tkinter_funcs fron the _tkagg.cpp c-extension working on PyPy, so in the mean time I fleshed out this approach to see if it is functional.

mattip commented Nov 5, 2017 •
edited by dopplershift
Loading

Copy link
Copy Markdown
Contributor Author

I actually needed to change very little to get this working, in the end I:

  • modified the private calls to pass "ptr height width" instead of id(array)
  • added another case to the code on non-win32 that searches for the shared object that works with PyPy's cffi module tk._tkinter.tklib_cffi.__file__

On PyPy unfortunately there seems to be an issue with opening the "configure subplot" subfigure on a basic plot, the mouse events are not reliably reaching the event handlers in lib/matplotlib/widgets.py, maybe a threading issue or competing event loops?

_tkagg.tkinit(tk.interpaddr(), 1)
else:
# very old python?
_tkagg.tkinit(tk, 0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

interpaddr was added in 1998(! python/cpython@9d1b7ae) so I cannot actually imagine a case where this is triggered today (but that can go to another PR of course)

mattip commented Nov 7, 2017

Copy link
Copy Markdown
Contributor Author

@tacaswell I got a mail reviewing the changes to setupext.py but cannot see it here, I removed the reference to py_converters.cpp since it is no longer needed. It was used to convert the python-level id(ndarray) to a C-level ndarray. Now I changed the code to pass in ptr height width instead, so the conversion does not require any knowlege about ndarrays

mattip commented Nov 7, 2017

Copy link
Copy Markdown
Contributor Author

How do I fix the codecov/patch check failure?

Copy link
Copy Markdown
Contributor

Don't worry about the codecov check there. The Tk GUI code, unfortunately, has no automated tests for CI to run.

anntzer commented Nov 7, 2017

Copy link
Copy Markdown
Contributor

We tend to ignore that check to be honest...

mattip commented Nov 23, 2017

Copy link
Copy Markdown
Contributor Author

ping

Comment thread src/_tkagg.cpp Outdated
# define SIZE_T_FORMAT "%zu"
# define IMG_FORMAT "%zu %d %d"
#endif
# define BBOX_FORMAT "%f %f %f %f"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

extra space?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

fixed in cc7b73e

Comment thread src/_tkagg.cpp Outdated
deststride = 4 * destwidth;

destbuffer = new agg::int8u[deststride * destheight];
destbuffer = new uint8_t[deststride * destheight];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

any reason for the change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

now it no longer uses #include py_converters.h which supplied the agg:int8u

Comment thread src/_tkagg.cpp Outdated
return TCL_ERROR;
}

if (sscanf(argv[4], BBOX_FORMAT, &x1, &x2, &y1, &y2) == 4) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

should probably error out cleanly if an invalid string is passed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

yesish, these are basically "private" functions parsing a call from python, but I will add more checking code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

updated in cc7b73e

Comment thread src/_tkagg.cpp Outdated
has_bbox = true;
}
else {
else if (bbox_parse == 1 && x1 == 0){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

parens

anntzer commented Nov 24, 2017

Copy link
Copy Markdown
Contributor

Can you rebase on master (to try to make appveyor pass... perhaps)?

Comment thread src/_tkagg.cpp
desty = hdata - y2;
destwidth = x2 - x1;
destheight = y2 - y1;
destx = (int)x1;

anntzer Nov 24, 2017 •
edited
Loading

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Shouldn't BBOX_FORMAT just be 4 integers and just use integers all along? (not sure if tk would have the bad idea to always cast things to float)

Edit: Actually I guess not, what should really happen is that we should explicitly cast on the caller's side but this can just go as it is for now...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

The call sequence is backend.blit(image, bbox) -> tkagg.py:blit(image, bbox) -> PyAggImagePhoto(as_string(image, bbox)) so we cannot change the root backend.blit call. AFAICT the choice is:

  • convert early in tkagg.py:blit
  • convert later in PyAggImagePhoto

I usually prefer converting as late as possible to postpone rounding and allow future refactoring with floats to be as painless as possible, but will flow with whatever is matplotlib best practices

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I think we can leave it as it is for now, we were using floats to start with and we can change that later.

anntzer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

assuming appveyor passes

Tested locally on cpython, not actually tested myself on pypy...

mattip commented Nov 24, 2017

Copy link
Copy Markdown
Contributor Author

thanks, I tested on pypy HEAD and tkagg now works. However the way matplotlib uses weakref.ref in callbacks exposes a bug in the JIT, am working on distilling it so I can report and get it fixes

mattip commented Nov 28, 2017

Copy link
Copy Markdown
Contributor Author

just to be clear, the weakref issue is not a matplotlib issue, rather a PyPy issue that matplotlib exposes

mattip commented Dec 2, 2017

Copy link
Copy Markdown
Contributor Author

after #9899 was merged, this is all that is needed for the next release of PyPy to work with the TkAgg backend

embedding_in_tk2_sgskip is essentially a slightly simplified duplicate
of embedding_in_tk_sgskip.
Comment thread src/_tkagg.cpp Outdated
deststride = 4 * destwidth;

destbuffer = new agg::int8u[deststride * destheight];
destbuffer = new uint8_t[deststride * destheight];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Why change away from the agg types here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Previously there was a conversion from a PyArrayObject * (in other words ndarray) to a data pointer, width, height, etc via py_converters. Now I pass that information directly from python. I no longer need the "py_converters.cpp" and ""py_converters.h" since there is no use of ndarray in the c++ code. Should I leave the include for this one type definition?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I am concerned about the corner case where unint8_t and agg:int8u are different underlying types. Not sure how likely that actually is, hence leaning towards being conservative about changing it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I wonder what different types you think these can be.
I would also bet that there must be parts of the code where we assume that this is interconvertible with np.uint8, or that this fits in a single byte... doesn't leave you a lot of options!

mattip commented Dec 11, 2017

Copy link
Copy Markdown
Contributor Author

I never mentioned that what I thought was a PyPy weakref or JIT issue was actually solved by PR #9899 so this PR is all that is needed for TkAgg and PyPy

mattip commented Dec 13, 2017

Copy link
Copy Markdown
Contributor Author

what's up with docs build? It seems to have timed out with no connection to my pull request

@tacaswell converted back to agg::int8u

mattip commented Dec 19, 2017 •
edited
Loading

Copy link
Copy Markdown
Contributor Author

what's up with docs build? It seems to have timed out with no connection to my pull request

@tacaswell converted back to agg::int8u

edit: docs build seems to have passed

jklymak commented Dec 19, 2017

Copy link
Copy Markdown
Member

Sometimes the builds need to be restarted manually because the host has a problem...

mattip commented Jan 11, 2018

Copy link
Copy Markdown
Contributor Author

can I get this marked 2.2-critical?

anntzer added the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Jan 11, 2018

anntzer commented Jan 11, 2018

Copy link
Copy Markdown
Contributor

"Making PyPy work" sounds like a good thing to have...

anntzer commented Jan 12, 2018

Copy link
Copy Markdown
Contributor

By the way would be nice to add a whatsnew entry (including info about what versions of PyPy are supposed to work).

mattip commented Jan 12, 2018

Copy link
Copy Markdown
Contributor Author

Not sure 270f05d is the proper way to do it, let me know if I should have done it differently

Copy link
Copy Markdown
Member

Perfect @mattip

tacaswell merged commit 3bb328f into matplotlib:master Jan 12, 2018

Copy link
Copy Markdown
Member

Thanks @mattip !

QuLogic modified the milestones: needs sorting, v2.2.0 Feb 12, 2018
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

GUI: tk Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants


Back | FazBrowse Home | New Git URL