You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
BUG: PyArray_CheckAxis possibly not working correctly #27194
I'm trying to fix some bugs in Pytensor's C code after moving to numpy 2.0. There is a function that essentially calls PyArray_CumSum with axis = None (which I have updated to mean axis = NPY_RAVEL_AXIS), and there is an error if NPY_RAVEL_AXIS is passed for axis, along with a 2D input array. If I ravel the input array and pass 0 for axis, then the test that calls Pytensor's cumsum function (which calls PyArray_CumSum) passes.
Since PyArray_CheckAxis should ravel in the input array and set axis to 0, it seems that perhaps it is failing.
The error message (below) is actually raised in the accumulate ufunc when trying to get an NpyIter object. From reading that code, I got the impression that for axis = None, it shouldn't use an iterator. I'm not sure what condition is setting "need_outer_iterator" to true. Also, I can't see from ufunc code (lines 2663-2666 in _cor/src/umath/ufunc_object.c) how op_axes[0][0] could be 1, since it seems to be set to 0.
Can you please share your updated code? I don't see what or even why it could be wrong in NumPy so before trying to see anything weird there, would prefer to see that part. Unless maybe you are passing in matrices? But even then I don't think anything changed.
np.add.accumulate(np.ones((1, 3)), out=np.zeros(3), axis=0) # or axis=1
since I don't see anything obviously wrong in your code.
So maybe still related to matrices? Those would definitely create the situation where the input should be raveled, but is not, causing this type of situation:
But that isn't new in NumPy 2, the above fails identically on 1.26.
So, I am sorry, but I think I have to ask you to check exactly what values are passing through. (In case you are not aware of it, the simplest way to add a print is: PySys_FormatStdout()) (EDIT: sorry had WriteStdout first, FormatStdout of course).
Thanks for the suggestions, I'm a bit out of my depth here (and in fact, was using C assert statements for debugging rather than printing...). I agree that it seems unlikely to be a numpy issue at root.
PyTensor matrices are built on ndarrays (as far as I can see), so I don't think that's the issue, but I'll see what the print statements say. Also, if I force the test to use the Python implementation, the test passes. The python code just calls out = np.cumsum(in, axis=None).
(For now, I'm not using params->c_axis in the case that axis is None because changes to the c_axis function don't seem to be picking up the right value for NPY_RAVEL_AXIS. So for axis = None (in python), I'm explicitly setting int axis = NPY_RAVEL_AXIS; in the C code.)
I'll get back to you with more details after I debug further. Thanks again.
I thought it was odd that the values in the newly assigned Z are the same as the values in X, but the same error occurs if instead
Z = (PyArrayObject*) PyArray_ZEROS(1, shape, PyArray_TYPE(Z), PyArray_IS_F_CONTIGUOUS(Z));
After this assignment, Z contains zeros and X contains its original values.
Incidentally, the value I set for c_axis to replace np.MAXDIMS wasn't matching NPY_RAVEL_AXIS because this is -1 instead of the smallest int32. I pip updated numpy from 2.0.0rc to 2.0.1 at some point. Could that be causing a problem? (I have another test that fails only if axis = -1, but passes if axis = ndim - 1, which could be explained by NPY_RAVEL_AXIS == -1.)
OK, that clearly explains what is wrong. And like a bug/typo :/. It needs to be defined to NPY_INT_MIN, and is not. Do you vendor the compat.h? In that case, please modify it to read:
Sorry, modifying wouldn't really work, since it would use the NumPy version if it exists, I guess. Could only copy the definition with a different name I guess.
Should fix this for the 2.1 (and 2.0.2 release), though.
Activity
seberg commentedon Aug 13, 2024
Can you please share your updated code? I don't see what or even why it could be wrong in NumPy so before trying to see anything weird there, would prefer to see that part. Unless maybe you are passing in matrices? But even then I don't think anything changed.
seberg commentedon Aug 13, 2024
So this creates the error:
since I don't see anything obviously wrong in your code.
So maybe still related to matrices? Those would definitely create the situation where the input should be raveled, but is not, causing this type of situation:
But that isn't new in NumPy 2, the above fails identically on 1.26.
So, I am sorry, but I think I have to ask you to check exactly what values are passing through. (In case you are not aware of it, the simplest way to add a print is:
PySys_FormatStdout()) (EDIT: sorry had WriteStdout first, FormatStdout of course).brendan-m-murphy commentedon Aug 13, 2024
Thanks for the suggestions, I'm a bit out of my depth here (and in fact, was using C assert statements for debugging rather than printing...). I agree that it seems unlikely to be a numpy issue at root.
PyTensor matrices are built on ndarrays (as far as I can see), so I don't think that's the issue, but I'll see what the print statements say. Also, if I force the test to use the Python implementation, the test passes. The python code just calls
out = np.cumsum(in, axis=None).I pushed the updates to
extra_opsto my fork: https://github.com/brendan-m-murphy/pytensor/pull/2/files#diff-f290a044a176b9391cf80035cb2ef33add7070cc67aa85f29b62b1d1270f7091(For now, I'm not using
params->c_axisin the case thataxisisNonebecause changes to thec_axisfunction don't seem to be picking up the right value forNPY_RAVEL_AXIS. So foraxis=None(in python), I'm explicitly settingint axis = NPY_RAVEL_AXIS;in the C code.)I'll get back to you with more details after I debug further. Thanks again.
brendan-m-murphy commentedon Aug 13, 2024
This is what I get from the print outs (I'm using
XandZwherepytensor/tensor/extra_ops.py::CumSum.c_codehas{x}and{z}):The function call is then:
The variable
Zis NULL initially, and sinceaxis == NPY_RAVEL_AXIS, it is set viaI thought it was odd that the values in the newly assigned
Zare the same as the values inX, but the same error occurs if insteadAfter this assignment,
Zcontains zeros andXcontains its original values.Incidentally, the value I set for
c_axisto replacenp.MAXDIMSwasn't matchingNPY_RAVEL_AXISbecause this is -1 instead of the smallest int32. I pip updated numpy from 2.0.0rc to 2.0.1 at some point. Could that be causing a problem? (I have another test that fails only ifaxis = -1, but passes ifaxis = ndim - 1, which could be explained byNPY_RAVEL_AXIS == -1.)seberg commentedon Aug 13, 2024
OK, that clearly explains what is wrong. And like a bug/typo :/. It needs to be defined to
NPY_INT_MIN, and is not. Do you vendor thecompat.h? In that case, please modify it to read:seberg commentedon Aug 13, 2024
Sorry, modifying wouldn't really work, since it would use the NumPy version if it exists, I guess. Could only copy the definition with a different name I guess.
Should fix this for the 2.1 (and 2.0.2 release), though.
brendan-m-murphy commentedon Aug 13, 2024
Yes, modifying the compat header doesn't seem to help. That would be great if it's fixed in an upcoming release, thanks!
seberg commentedon Aug 13, 2024
If it unblocks you in the moment, you can use that exact line I think, just need to define to a custom name, unfortunately:
brendan-m-murphy commentedon Aug 13, 2024
Ah okay, I see what you mean, thanks.