- 
                Notifications
    You must be signed in to change notification settings 
- Fork 106
MAINT: store default endianness state in a context variable #245
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
Conversation
| I just verified that the versions of the tests I added here in the latest version of this PR fail on 3.14.0 using the state of things in the current master branch with a C static global variable: The async failure happens more often on my machine but the multithreaded case also fails about 25% of the time. I haven't seen any failures using the context variable implementation in this PR. | 
| Thanks @ngoldbaum for working on supporting free-threaded Python! I have started looking into the free-threaded Python myself, and came across your PyCon talk on this subject. I am still not too familiar with this topic, and find the different levels on which one may support free-threading, and how it relates to multiple module initialization a bit confusing. I would like to learn more, but feel like it's hard to grasp the big picture. Are there other resources / videos on this topic you can recommend? | 
| First, I want to point out that this PR fixes a bug that you can trigger on the GIL-enabled build. While I'm working on this to support the free-threaded build, IMO this PR is unrelated to the free-threaded build and you should fix the bug I'm fixing regardless of considerations around the free-threaded build. The GIL only protects state inside of the interpreter - it doesn't protect state in third-party extensions like the global endianness state I'm fixing here. Now, for documentation on free-threading there's the docs we've been maintaining at https://py-free-threading.github.io. My piece of the PyCon talk covered the material on this page which covers porting C extensions. There's also the more general advice for porting any arbitrary package to support the free-threaded build that Lysandros covered. The talk was pretty constrained for time so those pages go into a lot more detail than the talk. The general advice covers the levels of support concept. If you're already familiar with multithreaded C/C++ programming, the trickiest concept to wrap your head around IMO is what a critical section is exactly and what it protects. It offers relatively weak guarantees, but it has the advantage of preventing deadlocks and providing similar guarantees to what the GIL provided extension authors, so it's often convenient to use to make code safe that relied on the GIL. These docs do a great job of covering that. If you're not familiar with multithreaded C/C++ programming, I've heard "C++: Concurrency in Action" is a good textbook. If you're familiar with Rust syntax, I found Rust atomics and Locks to be excellent and it has the side benefit of being free on the authors' website. As far as videos go, maybe take a look at David Woods' EuroPython talk on parallelism in Cython? He was talking about thread safety in Cython code but most of what he's saying applies to a C extension as well and I think you're at least a little familiar with Cython already. If you want to learn more about multithreaded programming in Python in general or specifically on the free-threaded build, I'd encourage you to read through the  I'm also happy to set up a call if you'd like a lower latency conversation about this stuff. We're also moderating a discord server if you want to pop in and chat. | 
d0db246    to
    5e10790      
    Compare
  
    | The latest changes add, document, and test a new  | 
| Thanks Nathan, for the detailed response and for adding the new context manager.  I should let you know about the script  | 
| Thanks for the comment, sent you an invite for Friday. | 
| After talking @ngoldbaum, we have decided to remove the global default endianness state completely, and that I will make an experimental thread-free enabled release of bitarray in a few days. | 
Towards supporting free-threaded Python, see #234 (comment)
I haven't benchmarked this but I also don't see any benchmarks in the repo. Do you think I should be worrying about any performance impact here?
get_c_default_endianprobably has more overhead than just reading a global.I could also store the state in a thread-local C variable, but I thought I'd propose this approach because I think this is the most idiomatic way to do this in Python and gives you async-safety for free along with setting up a public interface with a context manager.