-
-
Notifications
You must be signed in to change notification settings - Fork 11k
False positives for warning about writing to broadcast array in cython code #13929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
What cython version? |
For the astropy tests, I checked, and the code above still gives the deprecation warning for |
Hmm, hard to track, but it looks like cython is setting the buffer to writable. |
Or maybe just checking for writable.
|
So maybe a Cython bug, but probably not one we can track down for 1.17.0. |
Cython is requesting a writable buffer, and in this case I think NumPy should provide same. However, I wonder if cython handles read only arrays correctly? |
This fixes the example program
|
Indeed, when I explicitly set
so, you're right, cython expects its memoryview to be writeable. Apparently, one should be able to avoid that in more recent And this I can make to work, but only if I explicitly set my array as non-writeable (see below). Apparently, unless the array is explicitly set as From the numpy view, I'm not sure what would be best to work-around this...
|
More
|
Making a copy also fixes the problem as claimed.
|
@charris - your approach is simpler, but sort-of beats the point: I'm getting a warning that I may be writing, which is indeed dangerous, so I should not be just make the array I think the problem occurs because |
Actually, a simpler "solution" may be to add to the warning text that explicitly setting |
@mhvk Looking at astropy/astropy#8965, I wonder if a better route might be to just skip the deprecation warning and go straight to making the array readonly. CC: @mattip @eric-wieser |
Hmm, we could remove the warning from the flags, but then the deprecation warning is not too helpful, but I agree. If cython checks the flags upon conversion (and it must), then the whole deprecation may be tricky. If you add the |
@seberg The problem seems to be that we are using a flag that cython doesn't recognize. Cython still has to check the flags for other things (I think), so my sense is that we should skip the deprecation step. That will make the fix easier. Sometimes a clean cut is the least painful operation. |
The actual problem here is our own code I think: numpy/numpy/core/src/multiarray/buffer.c Lines 775 to 783 in 48efcc7
If we change that "dubious" behaviour, the warning can be silenced using the |
Ah, the buffer protocol cannot indicate readonly specifically (just request writeable). So I suppose we could simply return a readonly buffer right away when the user does not ask for writable specifically. That jumps the deprecation a little, but is likely fine. The only thing I find a bit annoying about it, is that without the deprecation, it might be a bit hard to see why an array is readonly, but I suppose that cannot be helped. |
So yeah, jumping the deprecation might be the best way and we can do that specific to the buffer protocol: Patch to jump deprecation for the buffer protocol:diff --git a/numpy/core/src/multiarray/buffer.c b/numpy/core/src/multiarray/buffer.c
index d8ad80266..4041b055f 100644
--- a/numpy/core/src/multiarray/buffer.c
+++ b/numpy/core/src/multiarray/buffer.c
@@ -771,17 +771,6 @@ array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
goto fail;
}
}
- /*
- * If a read-only buffer is requested on a read-write array, we return a
- * read-write buffer, which is dubious behavior. But that's why this call
- * is guarded by PyArray_ISWRITEABLE rather than (flags &
- * PyBUF_WRITEABLE).
- */
- if (PyArray_ISWRITEABLE(self)) {
- if (array_might_be_written(self) < 0) {
- goto fail;
- }
- }
if (view == NULL) {
PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer");
@@ -797,7 +786,14 @@ array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
view->buf = PyArray_DATA(self);
view->suboffsets = NULL;
view->itemsize = PyArray_ITEMSIZE(self);
- view->readonly = !PyArray_ISWRITEABLE(self);
+ /*
+ * Set a requested buffer to readonly also if the array will be readonly
+ * after a deprecation. This jumps the deprecation, but avoiding the
+ * warning is not convenient here and a warning is given if a writeable
+ * buffer is requested.
+ */
+ view->readonly = (!PyArray_ISWRITEABLE(self) ||
+ PyArray_CHKFLAGS(self, NPY_ARRAY_WARN_ON_WRITE));
view->internal = NULL;
view->len = PyArray_NBYTES(self);
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { I am not sure if that diff will force you to use the |
It's possible we should just rollback the warning on accessing the writeable attribute, it doesn't provide a huge amount of value, and sounds like with cython it comes with a high cost. @seberg: IMO forcing cython to use const for read-only arrays would be a really good idea, if there's a way to make that happen |
My patch works for me anyway (in the sense that either Cython does indeed force the |
Thanks for looking into this! I like the possibility of just using |
I wonder if the we should add that I can create a PR soon (although a few other things I would like to tick off the not-done list first). I suppose the next RC would tell us how things go. EDIT: Of course if someone beats me to it, I am happy as well :) |
When a buffer interface does not request a writeable buffer, simply pass a read-only one when the warn on write flag is set. This is to give an easier way forward with avoiding the deprecation warnings: Simply do not ask for a writeable buffer. It will break code that expects writeable buffers but does not ask for them specifically a bit harder than would be nice. But since such code probably should ask for it specifically, this is likely fine (an RC release has to find out). The main reason for this is, that this way it plays very will with cython, which requests writeable buffers explicitly and if declared `const` is happy about read-only (so that using `const` is the best way to avoid the warning and makes code cleaner). Closes numpygh-13929, numpygh-13974
When a buffer interface does not request a writeable buffer, simply pass a read-only one when the warn on write flag is set. This is to give an easier way forward with avoiding the deprecation warnings: Simply do not ask for a writeable buffer. It will break code that expects writeable buffers but does not ask for them specifically a bit harder than would be nice. But since such code probably should ask for it specifically, this is likely fine (an RC release has to find out). The main reason for this is, that this way it plays very will with cython, which requests writeable buffers explicitly and if declared `const` is happy about read-only (so that using `const` is the best way to avoid the warning and makes code cleaner). Closes numpygh-13929, numpygh-13974
@seberg - thanks for the fix - it works well, and getting us to declare arrays we don't write to as |
When a buffer interface does not request a writeable buffer, simply pass a read-only one when the warn on write flag is set. This is to give an easier way forward with avoiding the deprecation warnings: Simply do not ask for a writeable buffer. It will break code that expects writeable buffers but does not ask for them specifically a bit harder than would be nice. But since such code probably should ask for it specifically, this is likely fine (an RC release has to find out). The main reason for this is, that this way it plays very will with cython, which requests writeable buffers explicitly and if declared `const` is happy about read-only (so that using `const` is the best way to avoid the warning and makes code cleaner). Closes numpygh-13929, numpygh-13974
In astropy, we're getting loads of
DeprecationWarning
about possibly writing to a broadcast array from cythonized code. They all seem false positives, and may rather reflect something inCython
which I do not understand. But it can be reproduced with this trivial code below. For our particular case, I think this could be solved if one ensured the warning flag was only set if there was actual memory overlap inside the broadcast array.Sample file
broadcast.pyx
Corresponding
setup.py
:Compile and run with:
The text was updated successfully, but these errors were encountered: