-
Notifications
You must be signed in to change notification settings - Fork 11
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
Freethreading - module markers + CI #275
base: main
Are you sure you want to change the base?
Conversation
I was hitting this #263. If you find a way to use uv on Windows I'd be happy to use it. Maybe it's an issue with PATH? |
It's also an issue that the buffer protocol is even less sound in Python 3.13t. See discussion: https://discord.com/channels/1209263839632424990/1310572181138178129/1310572181138178129, https://alexgaynor.net/2022/oct/23/buffers-on-the-edge/, PyO3/pyo3#2824 I'm not sure what to do here. It's very beneficial to have the buffer protocol as an option. So perhaps just document to Python users that it's unsafe to mutate the Python buffer after passing it to rust? |
Yeah - I'm actually having a great deal of difficulty thinking of buffer protocol scenarios where freethreading would be unsound but not GIL-enabled; there's definitely a difference, but the complete lack of immutability guarantees is 99% of the problem (and serialized python execution (the GIL) addresses the remaining 1%). I think the safety note on By the sounds of (amongst other parts of that document) https://py-free-threading.github.io/porting/#dealing-with-thread-unsafe-objects and the comments on how numpy is going ahead with this, pathological cases (like resizing an array while it's being read) can just be left as "you're holding it wrong, enjoy the segfault", right up until the first bug report. |
Hmm it looks like I can't trigger the wheel builds on this repo from your PR.
Ideally this would also be surfaced to Python to be seen by Python users, but I'm not sure the right level of obtrusiveness for that. |
It would be nice if we didn't have to use a fork of |
Yeah, I noticed that in my own fork, though that seems to be fine now 🤔. It's likely a matter of: jobs can be triggered manually via workflow_dispatch, but not on pull requests (the wheels would need on: pull_request, which might be ok with cancel-in-progress); there doesn't seem to be a non-convoluted way to do manually triggered PR checks. |
Mm, not yet, probably mid-January (given the whole Christmas/NYE period is upon us) - it looks like it's down to a single mutex, probably test reconfiguration too. Obtrusiveness-wise, I can stick a (concise) spiel in the docstring of Array::frombuffer; I'd be hesitant to log anything at runtime higher than trace or debug level. |
I'm inclined not to merge this until numpy gets a stable release including the |
Yep, I'll stick this one (and related) in draft. |
Numpy merged its free-threading pr: PyO3/rust-numpy#471 (comment) |
Excellent, hopefully shouldn't be too much longer until that gets a release. I'll re-pin to the tip of |
Hrm, blocked by the pyO3 breaking change in 0.23.4 involving the |
…ompile without subsequent commit (avoid keeping it though, since it erases timezone info))
Can you merge in latest main? It should be fixed (with a temporary fixed offset workaround) |
b4caf36
to
fd1726b
Compare
With #304 it looks like this might actually be unblocked? |
@@ -33,7 +33,7 @@ fn check_debug_build(py: Python) -> PyResult<()> { | |||
Ok(()) | |||
} | |||
|
|||
#[pymodule] | |||
#[pymodule(gil_used = false)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this will always be true for the IO module. E.g. I might want to allow a Python HTTP library like aiohttp to be used for making the parquet
file reads
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, if unmodified (as in, rust locking structures cfg-gated on Py_GIL_DISABLED
) - there isn't code that allows that quite yet, right?
I should definitely take a crack at pytest-freethread in general before this is merged (at the very least CI for a single test in pyo3-arrow or core).
Thinking about it, pretty much all users of the freethreading build at the moment are other library maintainers porting their package to freethreading - this is probably a rare instance (especially given the main dependant is geoarrow.rust.io) where hard concurrency errors are preferred over RuntimeWarning
.
Oh, excellent - I gather the obstore py03 0.24.0 + object store 0.11 release unblocks this too (via #304 probably), right? That was my last blocker on this (the parquet crate's dependency on object store was involved in there somewhere). Thought I'd have to wait for the April parquet release. |
Yeah I made compatibility releases https://github.com/developmentseed/obstore/tree/main/pyo3-object_store#version-compatibility |
Alright, interesting data so far: even without freethreading (and with the gil_used property stripped out) we already get concurrency errors 😱 in test_ipc (3/200 iterations). Reproducible in both debug and release builds, so I'm inclined to believe they're genuine. With the gil_used flags set (oddly, despite the fact that this is still with the gil enabled), parquet kv metadata tests start throwing concurrency errors. Actually running the tests against an 3.13t build does work, but it's far more sensitive (I ended up having to resort to a pixi equivalent of the uv environment, after encountering segfaults on mismatched ABIs (manylinux_2_17 vs manylinux_2_34)). The good news on that front is core and compute are (as expected) safe in freethreading (out of an abundance of caution, I've run it at 24 threads and 10k iterations, not a peep). I think that answers it - we mark the IO tests as ineligible for concurrent tests and remove the gil_used attribute for arro3-io (importing it really should re-engage the GIL). |
Can you digest what this means? This applies only to python 3.13t? So our existing wheels are unaffected?
👍
Ok that's good at least.
I think that's fair. Though I would've expected the rust-based IO to handle concurrency well out of the box. Really I guess I'm curious which test it failed on? If you pass a string path to the Rust code, then I would assume that would work out of the box. But if you pass a file-like object to Rust, then it has to acquire the GIL to perform those reads from the Python file. I wouldn't be surprised if those were the failing tests. |
The IO test failures apply to both 3.13 and 3.13t (also probably all python versions that we build for). In retrospect, I should have spotted it - it's the roundtrip test, so this:
That throws with an invalid, unable to fill buffer error, in pyarrow. Of course that would fail eventually if you ran it concurrently on exactly the same file (whether through file paths or file descriptors), since there's very little stopping you from starting a read on a file currently being written to. |
Oh that makes sense. So there's likely nothing wrong with the library; that test just wasn't written with concurrency in mind. |
Yep, swapping the IO tests to use a I think we can probably just go with:
The great thing with the above is that demoting a module's freethreading status isn't particularly breaking, it just turns the GIL back on as soon as it's imported. |
I think #313 might already change that. Or at least, there are some functions that take in a |
Yet another fork (this time in setup-python), what exactly was it about setup-uv in windows that broke builds?
Verified wheel building run over at https://github.com/H-Plus-Time/arro3/actions/runs/12349504140.