Repository navigation
ENH: ArrayMethod sorting for built-in dtypes - #31278
MaanasArora wants to merge 5 commits into
Conversation
| return -1; | ||
| } | ||
| NPY_DT_SLOTS(dtypemeta)->sort_meth = sort_method_@name@->method; | ||
| Py_INCREF(sort_method_@name@->method); |
There was a problem hiding this comment.
For some reason, decrefing sort_method_@name@ causes a segfault, but this is leaking otherwise...
There was a problem hiding this comment.
Rather cryptic, I agree. The problem is that:
if (PyType_Ready(&PyArrayMethod_Type) < 0) {
return -1;
}
if (PyType_Ready(&PyBoundArrayMethod_Type) < 0) {
return -1;
}
needs to be called first. Remind me: object and void already use this due to being the default fallback path, I guess?
(But I agree that they are different enough, either way.)
There was a problem hiding this comment.
No I don't think so actually! object and void have a comparison function that is set here:
(PyArray_CompareFunc*)@from@_compare,
So, they are using the old path. That said it shouldn't at all be hard to use npy_default_sort_loop to take in a new comparison function for these.
There was a problem hiding this comment.
Hmm, if those use @from@_compare, can we then not do the same in #30415 (we discussed there somewhat at #30415 (review))
There was a problem hiding this comment.
Right, we could add that slot, but in the end, I suppose either way we'll be using a hard-coded path for those. (We'll probably just want to change the signature of the internal sort function to re-align, but it is hard-coded either way.)
One could add a "uses compare slot" auto-fill, but I am not sure it is worth it.
There was a problem hiding this comment.
Agreed, probably will hard-code those, so unclear whether filling the new slot with legacy sort is worth the tradeoff.
So for the DECREF... I guess this entire registration needed to be moved, so I added a function and called that after that block instead of within set_typeinfo, thanks!
There was a problem hiding this comment.
That should work yeah. If it is nicer, you can also just move the finalization of ArrayMethod_Type and BoundArrayMethod_Type to happen first, they don't have any dependencies and can happen much earlier.
There was a problem hiding this comment.
Ah okay, thanks! That does look nicer (less verbose), pushed!
seberg
left a comment
There was a problem hiding this comment.
Thanks, small comments, mostly how to fix the decref issue.
| } | ||
|
|
||
| return method->casting; | ||
| } |
There was a problem hiding this comment.
Hmmm, I guess we these them for timedelta64/datetime64 unfortunately, because it is parametric? (Just too bad, since this is all very simple in principle...)
There was a problem hiding this comment.
Unfortunate indeed, yes, it's because they're parametric. Given how often we're running into this, probably good to fix the issue somehow...
| return -1; | ||
| } | ||
| NPY_DT_SLOTS(dtypemeta)->sort_meth = sort_method_@name@->method; | ||
| Py_INCREF(sort_method_@name@->method); |
There was a problem hiding this comment.
Rather cryptic, I agree. The problem is that:
if (PyType_Ready(&PyArrayMethod_Type) < 0) {
return -1;
}
if (PyType_Ready(&PyBoundArrayMethod_Type) < 0) {
return -1;
}
needs to be called first. Remind me: object and void already use this due to being the default fallback path, I guess?
(But I agree that they are different enough, either way.)
mhvk
left a comment
There was a problem hiding this comment.
This looks nice! Main question I have is whether we can know these routines are actually used! You probably found out implicitly from errors... Can one test using the RuntimeError? Though it seems difficult to trigger in practice. So perhaps it can wait until we support descending...
|
Thanks @mhvk! Yes I found out via errors indeed, and confirmed with |
| return timsort_@suff@(data[0], dimensions[0], NULL); | ||
| #endif | ||
| default: | ||
| PyErr_Format(PyExc_RuntimeError, |
There was a problem hiding this comment.
I was wondering if it was possible to hit this RuntimeError -- but ideally from python. But that does seem tricky; having checked with print statements really is good enough!
There was a problem hiding this comment.
Yeah, not sure we can reach it easily. Although, once we follow up with reverse sorting, I think we'll have our proof at least?
There was a problem hiding this comment.
I think we can reach it by setting descending=True right? That should hit this?
Edit: sorry, I didn't recall we don't have it in Python yet for some reason! Yeah, that could be easier to test... no kwarg seems to hit this path right now in Python.
|
@MaanasArora happy to put this in if it helps with the other PR, just let me know. I think we'll want to move much of this to C++ to avoid that |
|
@seberg Yeah I rebased the other PR and moved sort loop creation to C++, so we can just go with that one I think! I'll close this. Thanks! |
Adds new-style sorting and argsorting array-methods (#29737) to built-in NumPy dtypes (bools, integers, floats, dates). This allows the new path in
PyArray_Sortto be functional for these, which will enable writing descending sorts soon after this. Supersedes #31273 to be much leaner. ping @seberg @mhvk - thanks!Still have to check the resolve descriptors setup and see if string/unicode can be added, but otherwise this is basically complete (modulo below refcount comment).
AI Disclosure
I used Claude to write the initial template
*_(arg)sort_loopfunctions but I cleaned it to the point there is little left of it.