Repository navigation
Conversation
|
Thanks for looking into this. But this is not the right abstraction layer to start with. We should handle this in the But, I think we need to start at the |
|
Thanks for the detailed explanation, I’ll go with your suggestion and look into handling this at the |
|
@seberg I did try to work towards moving this into the Rather than risk pushing an incomplete or incorrect fix, I think it’s best for me to step back and let someone with more experience in this area take it forward. Please let me know whether you’d prefer I close the PR, or leave it open in case it’s useful as a reference. |
Yeah, that may be quite tricky (or at least unwieldy, to make sure you get all). If you like, maybe push your start here and comment on the issue. Then we can close this PR but it may help someone else to dive in. (I am not actually sure how easy it is, for some places it should be pretty straight forward, but unwieldy, for gufuncs we may want to just reject it for now also.) |
38af602 to
0a2b8cf
Compare
|
Just commenting that this would be great to have for other purposes too -- I guess it means the step of converting all the old loops to array methods is becoming more pressing... |
|
Thanks for the insight, that makes sense. I don’t have much experience with this part of the codebase yet, so I didn’t want to create extra work for reviewers. If the direction of these changes looks good, I’d be happy to explore this further and would appreciate any guidance on how best to approach it. |
|
At a very brief glance the direction makes sense. One thing that probably is a good to simplify this is to not use it for the sin/cos. For example, we could make the Another note is that if that flag is set (or we can actually set it for the user), we should allow users to only give a We may not be able to cover quite all things with that one implementation, but most paths for sure. (E.g. I think casts behave the same way, but need a different logic, we may want to reject the flag for casts for now, just as it may be easier to reject it for gufuncs.) Hard to guarantee that we'll progress quickly. But if you are happy to prod it along, we can maybe also heavy handedly contribute to this at some point. |
|
Thanks for the feedback. I’d be happy to work on this, and for now I’ll proceed with the points you mentioned. |
| res = sfloat_add_loop("add", | ||
| bmeth->dtypes, (PyObject *)bmeth->method); | ||
| Py_DECREF(bmeth); | ||
| if (res < 0) { |
There was a problem hiding this comment.
I only made two actual changes here, the remaining changes come from resolving merge conflicts.
|
hii @seberg could you please review this, when you get chance and give some pointers to proceed with this, as we have still ci failures, sorry for delay progress. Thank you 😊 . |
seberg
left a comment
There was a problem hiding this comment.
Thanks, I think this looks pretty good, but the test needs to be modified to actually check that the contiguous iteration is guaranteed (and also for all types of calls).
There is a separate path for casts, we are not implementing it there yet, so the cast registration path should probably reject the flag for now.
| try: | ||
| from numpy._core import _scaled_float_dtype | ||
| except ImportError: | ||
| pytest.skip("Could not import _scaled_float_dtype for testing") |
There was a problem hiding this comment.
This should always be importable, even globally so.
| assert_array_equal(c, expected) | ||
|
|
||
| def test_ufunc_requires_contiguous_flag_sfloat(): | ||
| #GH#30413 |
There was a problem hiding this comment.
| #GH#30413 | |
| # gh-30413 |
Just habit/nit (also above)
| PyType_Slot add_slots[3] = { | ||
| {NPY_METH_resolve_descriptors, &add_sfloats_resolve_descriptors}, | ||
| {NPY_METH_strided_loop, &add_sfloats}, | ||
| {NPY_METH_contiguous_loop, &add_sfloats}, |
There was a problem hiding this comment.
To really test this, the add_sfloats loop needs to have a check that either the length is <= 1 or the stride is indeed contiguous.
Otherwise, the test exercises the code paths, but doesn't actually check that contiguous is guaranteed.
|
|
||
| c = a.copy() | ||
| np.add(c, b, out=c) | ||
| assert_array_equal(c, expected) |
There was a problem hiding this comment.
We should have plenty of tests for this, I think you can just remove this.
|
|
||
| res = np.add(a_non_contig, a_non_contig) | ||
| expected = (a_raw[::2] + a_raw[::2]).astype(dt) | ||
| assert_equal(res, expected) |
There was a problem hiding this comment.
We need to add tests for the other code paths (accumulate, reduce, etc.).
Reduce is also different, in that even with the flag the non-reduced argument isn't actually contiguous at all.
So either we need to clearly explain that in the docs, or just keep using strided_loop for now for that path but of course with the promise that the strides are contiguous except for the reduce case.
(Or maybe we could add a contiguous_reduce_loop, but one can always implement that with a custom get_loop also.)
| "Invalid flags set for ArrayMethod: 0x%x. (method: %s)", | ||
| spec->flags, spec->name); | ||
| return -1; | ||
| } |
There was a problem hiding this comment.
Hmmm, yeah, I guess this means if we add new flags (that don't really matter if there are there), downstream would have to guard by runtime version if on an older system.
But maybe that is fine, a check seems good as such really.
|
@seberg thanks for the review, I've applied changes as per your suggestion. As we have ci-failure, I've try to debug and fix, |
seberg
left a comment
There was a problem hiding this comment.
Thanks for the updates, small comments only. I am leaning towards requiring a strided_loop for simplicity right now TBH, even if it is a bit awkward.
(It seems to me we could move towards allowing just a contiguous loop from there.)
About testing, I would suggest you use a spin test workflow for NumPy. Unless you are doing a full pip install things should only rebuild what is needed (unless you modify some deep header files).
| assert(dimensions[0] <= 1 || | ||
| (strides[0] == sizeof(double) && | ||
| strides[1] == sizeof(double) && | ||
| strides[2] == sizeof(double))); |
There was a problem hiding this comment.
Please make this raise an error rather than an assert, since that way we are guaranteed to hit in during testing. Not quite sure you can use npy_gil_error here, but you can use an equivalent pattern.
(Otherwise it needs to be build with debugging but also it'll just hit an abort rather than a nice Python error.)
| /* | ||
| * Note: for reductions, only the result operand is guaranteed to be | ||
| * contiguous here; the reduction axis for the input operand may still | ||
| * be non-contiguous. |
There was a problem hiding this comment.
There is public documentation for NPY_METH_contiguous_loop which would need to mention this part.
Although, I am wondering if we shouldn't still force passing a NPY_METH_strided_loop even if the input would be guaranteed to be contiguous or a reduction.
(That also then allows distinguishing a probable reduce, from a non-reduce. By basically promising that the strided_loop must get a contiguous stride or a stride of zero.)
|
|
||
| def test_ufunc_requires_contiguous_flag_sfloat(): | ||
| # gh-30413 | ||
| _scaled_float_dtype = pytest.importorskip("numpy._core._scaled_float_dtype") |
There was a problem hiding this comment.
Fly-by: But we need to see why this import is failing, this is compiled with NumPy so it must be available. Probably the code is a bit wrong so you don't actually see the original error or so (I am not sure).
There was a problem hiding this comment.
thanks, i'll look more into this and let you know if i get something .
There was a problem hiding this comment.
@seberg need your help :) i haven't got much maybe if you have any feeling for any section where we could have done something wrong, I'd love dive there and debug . Thank you!
There was a problem hiding this comment.
IIRC, it just failed very early on or for rather simple code with this? If you are up for it, I would try to run it through gdb/lldb as a first shot: https://numpy.org/devdocs/dev/development_advanced_debugging.html#building-with-debug-symbols
Scrolling through, I can't see a very obvious issue, so I would have to run it through gdb as well.
There was a problem hiding this comment.
thanks , i'll also try to run and debug
| if (context.method->flags & NPY_METH_REQUIRES_CONTIGUOUS) { | ||
| op_flags[0] |= NPY_ITER_CONTIG; | ||
| op_flags[1] |= NPY_ITER_CONTIG; | ||
| op_flags[2] |= NPY_ITER_CONTIG; |
There was a problem hiding this comment.
I wonder if this might make things break, since some reductions must have a stride of 0 and can't be contig, but dunno
|
😿 we didn't had progress in this, but i have given a try in this before
but don't remember where i got stuck... I'll start again in this and make sure this time it moves forward and hopefully get merged soon . |
|
@seberg gentle ping , could you please have a look in this, when you get chance. I've updated with some changes. |
|
hii @seberg just pinning you, in case you missed notification, sorry i didn't mean to annoy by repeated mentioning you as i understand , due to large no. of PRs it takes time to review ... please ping you when you get chance 😊 |
|
Sorry, I'll have to come back to it in a while unfortunately. One reason for not jumping it, is that I think the contig flag to the iterator is dubious, i.e. see this commit and maybe especially the last test. So figuring out whether this will actually do the right thing is trickier then one would expect :/! Anther note: The contiguity request flag could maybe be a runtime flag, either way, by adding it to SFloat, you are completely disabling the other tests that uses the strided versions. |
fix #30413
NPY_UFUNC_REQUIRE_CONTIGUOUSflag and a flags field to PyUFuncObject.ufuncs (sin, cos).sinandcosto always expect contiguous data.Please let me know if my approach or fix needs any improvements . I’m open to feedback and happy to make changes based on suggestions.
Thank you !