Skip to content
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

Handling of Python element access in free-threading Python #6191

Open
da-woods opened this issue May 9, 2024 · 4 comments
Open

Handling of Python element access in free-threading Python #6191

da-woods opened this issue May 9, 2024 · 4 comments

Comments

@da-woods
Copy link
Contributor

da-woods commented May 9, 2024

Describe your issue

#6178 proposes adjusting __Pyx_GetItemInt_List_Fast to ignore boundscheck for free-threading Python and use PyList_GetItemRef (which does bounds-checking, but has the advantage that the reference counting is thread-safe).

That's probably fine as a short-term solution, but it seems reasonable that users might want to override this themselves for better performance.

There's a few options:

  • We interpret boundscheck(False) to mean "also don't bother with threadsafe reference counting". That isn't entirely consistent with its meaning since one could easy write something where multiple threads swapped out items from a constant-length list. In this case boundscheck should be unnecessary but threadsafe reference counting wouldn't be.
  • We ignore boundscheck(False) for list (and maybe other things) on free-threaded Python (what the PR proposes). It looks like we already ignore it for PyPy here too so it's consistent with the idea what it's an optimization hint and not an order. boundscheck(False) would continue to work correctly on memoryviews etc (which is really it's main use).
  • we add an extra threadsafe_reference_counting(False) directive that gives users the option to go back to the "fast path" even on the free-threading build with the understanding that it's their fault when they get it wrong. I think both boundscheck==False and threadsafe_reference_counting==False would be needed for the fast path on the free-threading build, but threadsafe_reference_counting could be completely ignored on other builds.
@lysnikolaou
Copy link
Contributor

Another question, somewhat related to this, is what assumptions should be made under CYTHON_ASSUME_SAFE_MACROS? Is it okay to assume that enabling CYTHON_ASSUME_SAFE_MACROS means that macros are okay to be used under the free-threading build as well?

@scoder
Copy link
Contributor

scoder commented May 13, 2024

it's an optimization hint and not an order

This. The directive allows us to avoid bounds checks where possible. If we need it for correctness, then we can't avoid it and that's it.

@da-woods
Copy link
Contributor Author

Another question, somewhat related to this, is what assumptions should be made under CYTHON_ASSUME_SAFE_MACROS? Is it okay to assume that enabling CYTHON_ASSUME_SAFE_MACROS means that macros are okay to be used under the free-threading build as well?

I think again it's something that we can choose to accept or ignore depending on how we feel (and it doesn't have to be consistent).

They're a little different in intent though - the macros aren't really intended to be used by normal users to enable/disable optimizations. They're available so people with an unsupported implementation of Python can attempt to get it working.

@scoder
Copy link
Contributor

scoder commented May 13, 2024

what assumptions should be made under CYTHON_ASSUME_SAFE_MACROS?

It means that (certain) macros cannot fail, specifically macros like Py*_GET_ITEM() and some others that use simple inlined code. There's a separate macro for Py*_GET_SIZE() as well since that tends to be even more safe.

the macros aren't really intended to be used by normal users to enable/disable optimizations. They're available so people with an unsupported implementation of Python can attempt to get it working.

Both, I'd say. Sometimes we find bugs, sometimes implementations evolve, and then it's helpful for users to be able to disable these macro options to keep their code working.

it's something that we can choose to accept or ignore depending on how we feel (and it doesn't have to be consistent).

Pretty much at that level, I agree. It's about allowing optimisations, not enforcing behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants